11 B站-一面
> Last Format Time:6/12/2026 21:03:57
代码
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 1000)
})
const promise2 = promise1.then((resolve) => {
console.log(resolve)
})
console.log('promise1', promise1)
console.log('promise2', promise2)
setTimeout(() => {
console.log('promise1', promise1)
console.log('promise2', promise2)
}, 2000)
// 错误
// promise1 promise2 Promise<> Promise<> promise1 promise2 error!!! 'success'
// 正确输出
// promise1 Promise { <pending> }
// promise2 Promise { <pending> }
// success
// promise1 Promise { 'success' }
// promise2 Promise { undefined }
- Promise 状态不可逆:一旦从 pending 变成 fulfilled 或 rejected,状态就永久锁定了。
- .then() 会返回新 Promise:promise2 并不是 promise1,它的状态和返回值取决于 .then() 回调里的执行情况。
- 没有 return 等于返回 undefined:.then() 的回调里如果不返回任何值,链式调用下一个 Promise 接收到的值就是 undefined。
这两个问题都是前端面试和实际开发中非常经典的异步编程与性能优化场景。下面为你分别提供清晰的实现方案:
用 Promise 实现图片的懒加载
实现懒加载的核心思路是:
- 使用
IntersectionObserverAPI 监听图片是否进入视口。 - 将图片的真实地址放在
data-src属性中,避免页面加载时直接请求图片。 - 当图片进入视口时,通过 Promise 封装图片加载过程,加载成功后将
data-src赋值给src。
以下是完整的代码实现:
<!-- HTML 结构:真实图片地址放在 data-src 中 -->
<img class="lazy-img" data-src="https://example.com/image1.jpg" alt="懒加载图片1" style="height: 300px; background: #f0f0f0;">
<img class="lazy-img" data-src="https://example.com/image2.jpg" alt="懒加载图片2" style="height: 300px; background: #f0f0f0;">
<script>
// 1. 用 Promise 封装图片加载过程
function preloadImage(src) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = () => reject(new Error(`图片加载失败: ${src}`));
img.src = src;
});
}
// 2. 创建 IntersectionObserver 实例
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
const realSrc = img.dataset.src;
// 使用 Promise 加载图片
preloadImage(realSrc)
.then(() => {
img.src = realSrc; // 加载成功后替换 src
img.classList.add('loaded');
observer.unobserve(img); // 加载完成停止观察
})
.catch((err) => {
console.error(err);
observer.unobserve(img); // 失败也要停止观察,避免死循环
});
}
});
}, {
rootMargin: '100px 0px' // 提前 100px 开始加载
});
// 3. 开始观察所有带有 lazy-img 类的图片
document.querySelectorAll('.lazy-img').forEach(img => {
observer.observe(img);
});
</script>
用 Promise 实现红绿灯交替(红3s, 黄1s, 绿3s)
实现红绿灯无限循环的关键在于:利用 Promise 配合 setTimeout 控制时间,并通过递归(或 .then 链末尾再次调用自身)来实现无限循环。
// 封装一个通用的亮灯函数,返回一个 Promise
function lightUp(color, duration) {
return new Promise((resolve) => {
console.log(`${color}灯亮起`);
setTimeout(() => {
resolve(); // 指定时间后结束当前 Promise
}, duration);
});
}
// 定义红绿灯循环函数
function trafficLight() {
// 按照 红 -> 黄 -> 绿 的顺序链式调用
lightUp('红', 3000)
.then(() => lightUp('黄', 1000))
.then(() => lightUp('绿', 3000))
.then(() => {
// 一轮结束后,再次调用自身,实现无限循环
trafficLight();
});
}
// 启动红绿灯
trafficLight();
实现原理解析
lightUp函数接收颜色和持续时间,返回一个在指定时间后resolve的 Promise。trafficLight函数通过.then()将红、黄、绿三个异步操作串联起来,保证了严格的执行顺序。- 在绿灯的 Promise 完成后,再次调用
trafficLight(),从而形成一个完美的异步闭环。